home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / DDJ0192.ARJ / DIALBOX.C < prev    next >
Text File  |  1991-10-10  |  20KB  |  866 lines

  1. /* ----------------- dialbox.c -------------- */
  2.  
  3. #include "dflat.h"
  4.  
  5. static char path[MAXPATH];
  6. static char drive[MAXDRIVE] = " :";
  7. static char dir[MAXDIR];
  8. static char name[MAXFILE];
  9. static char ext[MAXEXT];
  10.  
  11. static int inFocusCommand(DBOX *);
  12. static void dbShortcutKeys(DBOX *, int);
  13. static int ControlProc(WINDOW, MESSAGE, PARAM, PARAM);
  14. static void ChangeFocus(WINDOW, int);
  15. static CTLWINDOW *AssociatedControl(DBOX *, enum commands);
  16. static void SetRadioButton(DBOX *, CTLWINDOW *);
  17.  
  18. static int SysMenuOpen;
  19.  
  20. int DialogProc(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
  21. {
  22.     DBOX *db = wnd->extension;
  23.     CTLWINDOW *ct;
  24.     WINDOW cwnd;
  25.     int rtn;
  26.  
  27.     switch (msg)    {
  28.         case CREATE_WINDOW:
  29.             rtn = BaseWndProc(DIALOG, wnd, msg, p1, p2);
  30.             ct = db->ctl;
  31.             while (ct->class)    {
  32.                 int attrib = VISIBLE;
  33.                 if (TestAttribute(wnd, NOCLIP))
  34.                     attrib |= NOCLIP;
  35.                 if (wnd->Modal)
  36.                     attrib |= SAVESELF;
  37.                 ct->vtext = ct->itext;
  38.                 ct->setting = ct->isetting;
  39.                 if (ct->class == EDITBOX && ct->dwnd.h > 1)
  40.                     attrib |= (MULTILINE | HASBORDER);
  41.                 else if (ct->class == LISTBOX || ct->class == TEXTBOX)
  42.                     attrib |= HASBORDER;
  43.                 cwnd = CreateWindow(ct->class,
  44.                              ct->dwnd.title,
  45.                              ct->dwnd.x+GetClientLeft(wnd),
  46.                              ct->dwnd.y+GetClientTop(wnd),
  47.                              ct->dwnd.h,
  48.                              ct->dwnd.w,
  49.                              ct,
  50.                              wnd,
  51.                              ControlProc,
  52.                              attrib);
  53.                 if ((ct->class == EDITBOX || ct->class == COMBOBOX) &&
  54.                         ct->itext != NULL)
  55.                     SendMessage(cwnd, ADDTEXT, (PARAM) ct->itext, 0);
  56.                 if (ct->class != BOX &&
  57.                     ct->class != TEXT &&
  58.                         wnd->dFocus == NULL)
  59.                     wnd->dFocus = ct;
  60.                 ct++;
  61.             }
  62.             return rtn;
  63.         case SETFOCUS:
  64.             if (wnd->Modal)    {
  65.                 if (p1)
  66.                     SendMessage(inFocus, SETFOCUS, FALSE, 0);
  67.                 inFocus = p1 ? wnd : NULL;
  68.                 return TRUE;
  69.             }
  70.             break;
  71.         case SHIFT_CHANGED:
  72.             if (wnd->Modal)
  73.                 return TRUE;
  74.             break;
  75.         case LEFT_BUTTON:
  76.             if (WindowSizing || WindowMoving)
  77.                 return FALSE;
  78.             if (HitControlBox(wnd, p1-GetLeft(wnd), p2-GetTop(wnd)))    {
  79.                 PostMessage(wnd, KEYBOARD, ' ', ALTKEY);
  80.                 return TRUE;
  81.             }
  82.             ct = db->ctl;
  83.             while (ct->class)    {
  84.                 WINDOW cwnd = ct->wnd;
  85.                 if (ct->class == COMBOBOX)    {
  86.                     if (p2 == GetTop(cwnd))    {
  87.                         if (p1 == GetRight(cwnd)+1)    {
  88.                             SendMessage(cwnd, msg, p1, p2);
  89.                             return TRUE;
  90.                         }
  91.                     }
  92.                     if (GetClass(inFocus) == LISTBOX)
  93.                         SendMessage(wnd, SETFOCUS, TRUE, 0);
  94.                 }
  95.                 else if (ct->class == SPINBUTTON)    {
  96.                     if (p2 == GetTop(cwnd))    {
  97.                         if (p1 == GetRight(cwnd)+1 ||
  98.                                 p1 == GetRight(cwnd)+2)    {
  99.                             SendMessage(cwnd, msg, p1, p2);
  100.                             return TRUE;
  101.                         }
  102.                     }
  103.                 }
  104.                 ct++;
  105.             }
  106.             break;
  107.         case KEYBOARD:
  108.             if (WindowMoving || WindowSizing)
  109.                 break;
  110.             switch ((int)p1)    {
  111.                 case F1:
  112.                     ct = wnd->dFocus;
  113.                     if (ct != NULL)
  114.                         if (DisplayHelp(wnd, ct->help))
  115.                             return TRUE;
  116.                     break;
  117.                 case CTRL_FIVE:        /* same as SHIFT-TAB */
  118.                     if ((int)p2 & (LEFTSHIFT | RIGHTSHIFT))
  119.                         ChangeFocus(wnd, FALSE);
  120.                     break;
  121.                 case BS:
  122.                 case UP:
  123.                     ChangeFocus(wnd, FALSE);
  124.                     break;
  125.                 case ALT_F6:
  126.                 case '\t':
  127.                 case FWD:
  128.                 case DN:
  129.                     ChangeFocus(wnd, TRUE);
  130.                     break;
  131.                 case ' ':
  132.                     if (((int)p2 & ALTKEY) && TestAttribute(wnd, CONTROLBOX))    {
  133.                         SysMenuOpen = TRUE;
  134.                         BuildSystemMenu(wnd);
  135.                     }
  136.                     break;
  137.                 case CTRL_F4:
  138.                 case ESC:
  139.                     SendMessage(wnd, COMMAND, ID_CANCEL, 0);
  140.                     break;
  141.                 default:
  142.                     /* ------ search all the shortcut keys ----- */
  143.                     dbShortcutKeys(db, (int) p1);
  144.                     break;
  145.             }
  146.             if (wnd->Modal)
  147.                 return TRUE;
  148.             break;
  149.         case CLOSE_POPDOWN:
  150.             SysMenuOpen = FALSE;
  151.             break;
  152.         case LB_SELECTION:
  153.         case LB_CHOOSE:
  154.             if (SysMenuOpen)
  155.                 return TRUE;
  156.             SendMessage(wnd, COMMAND, inFocusCommand(db), msg);
  157.             break;
  158.         case COMMAND:
  159.             switch ((int) p1)    {
  160.                 case ID_OK:
  161.                 case ID_CANCEL:
  162.                     if ((int)p2 != 0)
  163.                         return TRUE;
  164.                     wnd->ReturnCode = (int) p1;
  165.                     if (wnd->Modal)
  166.                         PostMessage(wnd, ENDDIALOG, 0, 0);
  167.                     else
  168.                         SendMessage(wnd, CLOSE_WINDOW, TRUE, 0);
  169.                     return TRUE;
  170.                 case ID_HELP:
  171.                     if ((int)p2 != 0)
  172.                         return TRUE;
  173.                     return DisplayHelp(wnd, db->HelpName);
  174.                 default:
  175.                     break;
  176.             }
  177.             break;
  178.         case CLOSE_WINDOW:
  179.             if (!p1)    {
  180.                 SendMessage(wnd, COMMAND, ID_CANCEL, 0);
  181.                 return TRUE;
  182.             }
  183.             break;
  184.         default:
  185.             break;
  186.     }
  187.     return BaseWndProc(DIALOG, wnd, msg, p1, p2);
  188. }
  189.  
  190. int DialogBox(WINDOW wnd, DBOX *db, int Modal,
  191.     int (*wndproc)(struct window *, enum messages, PARAM, PARAM))
  192. {
  193.     int rtn;
  194.     CTLWINDOW *ct;
  195.     WINDOW oldFocus = inFocus;
  196.     WINDOW DialogWnd = CreateWindow(DIALOG,
  197.                         db->dwnd.title,
  198.                         db->dwnd.x,
  199.                         db->dwnd.y,
  200.                         db->dwnd.h,
  201.                         db->dwnd.w,
  202.                         db,
  203.                         wnd,
  204.                         wndproc,
  205.                         Modal ? SAVESELF : 0);
  206.     DialogWnd->Modal = Modal;
  207.     SendMessage(((CTLWINDOW *)(DialogWnd->dFocus))->wnd, SETFOCUS, TRUE, 0);
  208.     SendMessage(DialogWnd, SHOW_WINDOW, 0, 0);
  209.     SendMessage(DialogWnd, INITIATE_DIALOG, 0, 0);
  210.     if (Modal)    {
  211.         SendMessage(DialogWnd, CAPTURE_MOUSE, 0, 0);
  212.         SendMessage(DialogWnd, CAPTURE_KEYBOARD, 0, 0);
  213.         while (dispatch_message())
  214.             ;
  215.         rtn = DialogWnd->ReturnCode == ID_OK;
  216.         SendMessage(DialogWnd, RELEASE_MOUSE, 0, 0);
  217.         SendMessage(DialogWnd, RELEASE_KEYBOARD, 0, 0);
  218.         SendMessage(inFocus, SETFOCUS, FALSE, 0);
  219.         SendMessage(DialogWnd, CLOSE_WINDOW, TRUE, 0);
  220.         SendMessage(oldFocus, SETFOCUS, TRUE, 0);
  221.         if (rtn)    {
  222.             ct = db->ctl;
  223.             while (ct->class)    {
  224.                 ct->wnd = NULL;
  225.                 if (ct->class == RADIOBUTTON || ct->class == CHECKBOX)
  226.                     ct->isetting = ct->setting;
  227.                 ct++;
  228.             }
  229.         }
  230.         return rtn;
  231.     }
  232.     return FALSE;
  233. }
  234.  
  235. static int inFocusCommand(DBOX *db)
  236. {
  237.     CTLWINDOW *ct = db->ctl;
  238.     while (ct->class)    {
  239.         if (ct->wnd == inFocus)
  240.             return ct->command;
  241.         ct++;
  242.     }
  243.     return -1;
  244. }
  245.  
  246. CTLWINDOW *FindCommand(DBOX *db, enum commands cmd, int class)
  247. {
  248.     CTLWINDOW *ct = db->ctl;
  249.     while (ct->class)    {
  250.         if (ct->class == class)
  251.             if (cmd == ct->command)
  252.                 return ct;
  253.         ct++;
  254.     }
  255.     return NULL;
  256. }
  257.  
  258. WINDOW ControlWindow(DBOX *db, enum commands cmd)
  259. {
  260.     CTLWINDOW *ct = db->ctl;
  261.     while (ct->class)    {
  262.         if (ct->class != TEXT && cmd == ct->command)
  263.             return ct->wnd;
  264.         ct++;
  265.     }
  266.     return NULL;
  267. }
  268.  
  269. void PushRadioButton(DBOX *db, enum commands cmd)
  270. {
  271.     CTLWINDOW *ct = FindCommand(db, cmd, RADIOBUTTON);
  272.     if (ct != NULL)    {
  273.         SetRadioButton(db, ct);
  274.         ct->isetting = ON;
  275.     }
  276. }
  277.  
  278. static struct {
  279.     CTLWINDOW *rct;
  280. } rbs[MAXRADIOS];
  281.  
  282. static void SetRadioButton(DBOX *db, CTLWINDOW *ct)
  283. {
  284.     CTLWINDOW *ctt = db->ctl;
  285.     int i;
  286.  
  287.     /* --- clear all the radio buttons
  288.                 in this group on the dialog box --- */
  289.  
  290.     /* -------- build a table of all radio buttons at the
  291.             same x vector ---------- */
  292.     for (i = 0; i < MAXRADIOS; i++)
  293.         rbs[i].rct = NULL;
  294.     while (ctt->class)    {
  295.         if (ctt->class == RADIOBUTTON)
  296.             if (ct->dwnd.x == ctt->dwnd.x)
  297.                 rbs[ctt->dwnd.y].rct = ctt;
  298.         ctt++;
  299.     }
  300.  
  301.     /* ----- find the start of the radiobutton group ---- */
  302.     i = ct->dwnd.y;
  303.     while (i >= 0 && rbs[i].rct != NULL)
  304.         --i;
  305.     /* ---- ignore everthing before the group ------ */
  306.     while (i >= 0)
  307.         rbs[i--].rct = NULL;
  308.  
  309.     /* ----- find the end of the radiobutton group ---- */
  310.     i = ct->dwnd.y;
  311.     while (i < MAXRADIOS && rbs[i].rct != NULL)
  312.         i++;
  313.     /* ---- ignore everthing past the group ------ */
  314.     while (i < MAXRADIOS)
  315.         rbs[i++].rct = NULL;
  316.  
  317.     for (i = 0; i < MAXRADIOS; i++)    {
  318.         if (rbs[i].rct != NULL)    {
  319.             int wason = rbs[i].rct->setting;
  320.             rbs[i].rct->setting = OFF;
  321.             if (wason)
  322.                 SendMessage(rbs[i].rct->wnd, PAINT, 0, 0);
  323.         }
  324.     }
  325.     ct->setting = ON;
  326.     SendMessage(ct->wnd, PAINT, 0, 0);
  327. }
  328.  
  329. int RadioButtonSetting(DBOX *db, enum commands cmd)
  330. {
  331.     CTLWINDOW *ct = FindCommand(db, cmd, RADIOBUTTON);
  332.     if (ct != NULL)
  333.         return (ct->setting == ON);
  334.     return FALSE;
  335. }
  336.  
  337. static void ControlSetting(DBOX *db, enum commands cmd,
  338.                                     int class, int setting)
  339. {
  340.     CTLWINDOW *ct = FindCommand(db, cmd, class);
  341.     if (ct != NULL)
  342.         ct->isetting = setting;
  343. }
  344.  
  345. void SetCheckBox(DBOX *db, enum commands cmd)
  346. {
  347.     ControlSetting(db, cmd, CHECKBOX, ON);
  348. }
  349.  
  350. void ClearCheckBox(DBOX *db, enum commands cmd)
  351. {
  352.     ControlSetting(db, cmd, CHECKBOX, OFF);
  353. }
  354.  
  355. void EnableButton(DBOX *db, enum commands cmd)
  356. {
  357.     ControlSetting(db, cmd, BUTTON, ON);
  358. }
  359.  
  360. void DisableButton(DBOX *db, enum commands cmd)
  361. {
  362.     ControlSetting(db, cmd, BUTTON, OFF);
  363. }
  364.  
  365. int CheckBoxSetting(DBOX *db, enum commands cmd)
  366. {
  367.     CTLWINDOW *ct = FindCommand(db, cmd, CHECKBOX);
  368.     if (ct != NULL)
  369.         return (ct->isetting == ON);
  370.     return FALSE;
  371. }
  372.  
  373. char *GetDlgTextString(DBOX *db, enum commands cmd, CLASS class)
  374. {
  375.     CTLWINDOW *ct = FindCommand(db, cmd, class);
  376.     if (ct != NULL)
  377.         return ct->itext;
  378.     else
  379.         return NULL;
  380. }
  381.  
  382. void SetDlgTextString(DBOX *db, enum commands cmd, char *text, CLASS class)
  383. {
  384.     CTLWINDOW *ct = FindCommand(db, cmd, class);
  385.     if (ct != NULL)    {
  386.         ct->itext = realloc(ct->itext, strlen(text)+1);
  387.         if (ct->itext != NULL)
  388.             strcpy(ct->itext, text);
  389.     }
  390. }
  391.  
  392. static void Scrollers(WINDOW wnd)
  393. {
  394.     if (wnd->wlines > ClientHeight(wnd) &&
  395.             !TestAttribute(wnd, VSCROLLBAR))    {
  396.         AddAttribute(wnd, VSCROLLBAR);
  397.         SendMessage(wnd, BORDER, 0, 0);
  398.     }
  399. }
  400.  
  401. void PutComboListText(WINDOW wnd, enum commands cmd, char *text)
  402. {
  403.     CTLWINDOW *ct = FindCommand(wnd->extension, cmd, COMBOBOX);
  404.     if (ct != NULL)        {
  405.         WINDOW lwnd = ((WINDOW)(ct->wnd))->extension;
  406.         SendMessage(lwnd, ADDTEXT, (PARAM) text, 0);
  407.         Scrollers(lwnd);
  408.     }
  409. }
  410.  
  411. void PutItemText(WINDOW wnd, enum commands cmd, char *text)
  412. {
  413.     CTLWINDOW *ct = FindCommand(wnd->extension, cmd, EDITBOX);
  414.  
  415.     if (ct == NULL)
  416.         ct = FindCommand(wnd->extension, cmd, TEXTBOX);
  417.     if (ct == NULL)
  418.         ct = FindCommand(wnd->extension, cmd, COMBOBOX);
  419.     if (ct == NULL)
  420.         ct = FindCommand(wnd->extension, cmd, LISTBOX);
  421.     if (ct == NULL)
  422.         ct = FindCommand(wnd->extension, cmd, SPINBUTTON);
  423.     if (ct == NULL)
  424.         ct = FindCommand(wnd->extension, cmd, TEXT);
  425.     if (ct != NULL)        {
  426.         WINDOW cwnd = (WINDOW) (ct->wnd);
  427.         switch (ct->class)    {
  428.             case COMBOBOX:
  429.             case EDITBOX:
  430.                 SendMessage(cwnd, CLEARTEXT, 0, 0);
  431.                 SendMessage(cwnd, ADDTEXT, (PARAM) text, 0);
  432.                 if (!isMultiLine(cwnd))
  433.                     SendMessage(cwnd, PAINT, 0, 0);
  434.                 Scrollers(cwnd);
  435.                 break;
  436.             case LISTBOX:
  437.             case TEXTBOX:
  438.             case SPINBUTTON:
  439.                 SendMessage(cwnd, ADDTEXT, (PARAM) text, 0);
  440.                 Scrollers(cwnd);
  441.                 break;
  442.             case TEXT:    {
  443.                 SendMessage(cwnd, CLEARTEXT, 0, 0);
  444.                 SendMessage(cwnd, ADDTEXT, (PARAM) text, 0);
  445.                 SendMessage(cwnd, PAINT, 0, 0);
  446.                 break;
  447.             }
  448.             default:
  449.                 break;
  450.         }
  451.     }
  452. }
  453.  
  454. void GetItemText(WINDOW wnd, enum commands cmd, char *text, int len)
  455. {
  456.     CTLWINDOW *ct = FindCommand(wnd->extension, cmd, EDITBOX);
  457.  
  458.     if (ct == NULL)
  459.         ct = FindCommand(wnd->extension, cmd, COMBOBOX);
  460.     if (ct == NULL)
  461.         ct = FindCommand(wnd->extension, cmd, TEXTBOX);
  462.     if (ct == NULL)
  463.         ct = FindCommand(wnd->extension, cmd, TEXT);
  464.     if (ct != NULL)    {
  465.         WINDOW cwnd = (WINDOW) (ct->wnd);
  466.         if (cwnd != NULL)    {
  467.             switch (ct->class)    {
  468.                 case TEXT:
  469.                     if (GetText(cwnd) != NULL)    {
  470.                         unsigned char *cp = strchr(GetText(cwnd), '\n');
  471.                         if (cp != NULL)
  472.                             len = (int) (cp - GetText(cwnd));
  473.                         strncpy(text, GetText(cwnd), len);
  474.                         *(text+len) = '\0';
  475.                     }
  476.                     break;
  477.                 case TEXTBOX:
  478.                     if (GetText(cwnd) != NULL)
  479.                         strncpy(text, GetText(cwnd), len);
  480.                     break;
  481.                 case COMBOBOX:
  482.                 case EDITBOX:
  483.                     SendMessage(cwnd, GETTEXT, (PARAM) text, len);
  484.                     break;
  485.                 default:
  486.                     break;
  487.             }
  488.         }
  489.     }
  490. }
  491.  
  492. void GetDlgListText(WINDOW wnd, char *text, enum commands cmd)
  493. {
  494.     CTLWINDOW *ct = FindCommand(wnd->extension, cmd, LISTBOX);
  495.     int sel = SendMessage(ct->wnd, LB_CURRENTSELECTION, 0, 0);
  496.     SendMessage(ct->wnd, LB_GETTEXT, (PARAM) text, sel);
  497. }
  498.  
  499. static int dircmp(const void *c1, const void *c2)
  500. {
  501.     return stricmp(*(char **)c1, *(char **)c2);
  502. }
  503.  
  504. int DlgDirList(WINDOW wnd, char *fspec,
  505.                 enum commands nameid, enum commands pathid,
  506.                 unsigned attrib)
  507. {
  508.     int ax, i = 0, criterr = 1;
  509.     struct ffblk ff;
  510.     CTLWINDOW *ct = FindCommand(wnd->extension, nameid, LISTBOX);
  511.     WINDOW lwnd;
  512.     char **dirlist = NULL;
  513.  
  514.     CreatePath(path, fspec, TRUE, TRUE);
  515.  
  516.     if (ct != NULL)    {
  517.         lwnd = ct->wnd;
  518.         SendMessage(ct->wnd, CLEARTEXT, 0, 0);
  519.  
  520.         if (attrib & 0x8000)    {
  521.             union REGS regs;
  522.             char drname[15];
  523.             unsigned int cd, dr;
  524.  
  525.             cd = getdisk();
  526.             for (dr = 0; dr < 26; dr++)    {
  527.                 unsigned ndr;
  528.                 setdisk(dr);
  529.                 ndr = getdisk();
  530.                 if (ndr == dr)    {
  531.                     /* ------- test for remapped B drive ------- */
  532.                     if (dr == 1)    {
  533.                         regs.x.ax = 0x440e;        /* IOCTL function 14 */
  534.                         regs.h.bl = dr+1;
  535.                         int86(DOS, ®s, ®s);
  536.                         if (regs.h.al != 0)
  537.                             continue;
  538.                     }
  539.  
  540.                     sprintf(drname, "[%c:]", dr+'A');
  541.  
  542.                     /* ------ test for network or RAM disk ---- */
  543.                     regs.x.ax = 0x4409;        /* IOCTL function 9 */
  544.                     regs.h.bl = dr+1;
  545.                     int86(DOS, ®s, ®s);
  546.                     if (!regs.x.cflag)    {
  547.                         if (regs.x.dx & 0x1000)
  548.                             strcat(drname, " (Network)");
  549.                         else if (regs.x.dx == 0x0800)
  550.                             strcat(drname, " (RAMdisk)");
  551.                     }
  552.                     SendMessage(lwnd, ADDTEXT, (PARAM) drname, 0);
  553.                 }
  554.             }
  555.             setdisk(cd);
  556.         }
  557.  
  558.         while (criterr == 1)    {
  559.             ax = findfirst(path, &ff, attrib & 0x3f);
  560.             criterr = TestCriticalError();
  561.         }
  562.         if (criterr)
  563.             return FALSE;
  564.         while (ax == 0)    {
  565.             if (!((attrib & 0x4000) &&
  566.                     (ff.ff_attrib & (attrib & 0x3f)) == 0) &&
  567.                         strcmp(ff.ff_name, "."))    {
  568.                 char fname[15];
  569.                 sprintf(fname, (ff.ff_attrib & 0x10) ?
  570.                                 "[%s]" : "%s" , ff.ff_name);
  571.                 dirlist = realloc(dirlist, sizeof(char *)*(i+1));
  572.                 if (dirlist != NULL)    {
  573.                     dirlist[i] = malloc(strlen(fname)+1);
  574.                     if (dirlist[i] != NULL)
  575.                         strcpy(dirlist[i], fname);
  576.                     i++;
  577.                 }
  578.             }
  579.             ax = findnext(&ff);
  580.         }
  581.         if (dirlist != NULL)    {
  582.             int j;
  583.             /* -- sort file/drive/directory list box data -- */
  584.             qsort(dirlist, i, sizeof(void *), dircmp);
  585.  
  586.             /* ---- send sorted list to list box ---- */
  587.             for (j = 0; j < i; j++)    {
  588.                 SendMessage(lwnd, ADDTEXT, (PARAM) dirlist[j], 0);
  589.                 free(dirlist[j]);
  590.             }
  591.             free(dirlist);
  592.         }
  593.         if (lwnd->wlines > ClientHeight(lwnd))
  594.             AddAttribute(lwnd, VSCROLLBAR);
  595.         else
  596.             ClearAttribute(lwnd, VSCROLLBAR);
  597.         SendMessage(lwnd, SHOW_WINDOW, 0, 0);
  598.     }
  599.  
  600.     if (pathid)    {
  601.         fnmerge(path, drive, dir, NULL, NULL);
  602.         PutItemText(wnd, pathid, path);
  603.     }
  604.  
  605.     return TRUE;
  606. }
  607.  
  608. static CTLWINDOW *AssociatedControl(DBOX *db, enum commands Tcmd)
  609. {
  610.     CTLWINDOW *ct = db->ctl;
  611.     while (ct->class)    {
  612.         if (ct->class != TEXT)
  613.             if (ct->command == Tcmd)
  614.                 break;
  615.         ct++;
  616.     }
  617.     return ct;
  618. }
  619.  
  620. static void dbShortcutKeys(DBOX *db, int ky)
  621. {
  622.     CTLWINDOW *ct;
  623.     int ch = AltConvert(ky);
  624.  
  625.     if (ch != 0)    {
  626.         ct = db->ctl;
  627.         while (ct->class)    {
  628.             char *cp = ct->vtext;
  629.             while (cp && *cp)    {
  630.                 if (*cp == SHORTCUTCHAR && tolower(*(cp+1)) == ch)    {
  631.                     if (ct->class == TEXT)
  632.                         ct = AssociatedControl(db, ct->command);
  633.                     if (ct->class == RADIOBUTTON)
  634.                         SetRadioButton(db, ct);
  635.                     else if (ct->class == CHECKBOX)    {
  636.                         ct->setting ^= ON;
  637.                         SendMessage(ct->wnd, PAINT, 0, 0);
  638.                     }
  639.                     else if (ct->class)    {
  640.                         SendMessage(ct->wnd, SETFOCUS, TRUE, 0);
  641.                         if (ct->class == BUTTON)
  642.                             SendMessage(ct->wnd, KEYBOARD, '\r', 0);
  643.                     }
  644.                     return;
  645.                 }
  646.                 cp++;
  647.             }
  648.             ct++;
  649.         }
  650.     }
  651. }
  652.  
  653. /* generic window processor used by all dialog box control windows */
  654. static int ControlProc(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
  655. {
  656.     DBOX *db;
  657.     CTLWINDOW *ct;
  658.  
  659.     if (wnd == NULL)
  660.         return FALSE;
  661.     db = GetParent(wnd) ? GetParent(wnd)->extension : NULL;
  662.     ct = GetControl(wnd);
  663.  
  664.     switch (msg)    {
  665.         case CREATE_WINDOW:
  666.             ct = wnd->ct = wnd->extension;
  667.             wnd->extension = NULL;
  668.             if (ct != NULL)
  669.                 ct->wnd = wnd;
  670.             break;
  671.         case KEYBOARD:
  672.             switch ((int) p1)    {
  673.                 case F1:
  674.                     if (WindowMoving || WindowSizing)
  675.                         break;
  676.                     if (!DisplayHelp(wnd, ct->help))
  677.                         SendMessage(GetParent(wnd), COMMAND, ID_HELP, 0);
  678.                     return TRUE;
  679.                 case ' ':
  680.                     if (!((int)p2 & ALTKEY))
  681.                         break;
  682.                 case ALT_F6:
  683.                 case CTRL_F4:
  684.                 case ALT_F4:
  685.                     PostMessage(GetParent(wnd), msg, p1, p2);
  686.                     return TRUE;
  687.                 default:
  688.                     break;
  689.             }
  690.             if (GetClass(wnd) == EDITBOX)
  691.                 if (isMultiLine(wnd))
  692.                     break;
  693.             switch ((int) p1)    {
  694.                 case UP:
  695.                     if (!isDerivedFrom(wnd, LISTBOX))    {
  696.                         p1 = CTRL_FIVE;
  697.                         p2 = LEFTSHIFT;
  698.                     }
  699.                     break;
  700.                 case BS:
  701.                     if (!isDerivedFrom(wnd, EDITBOX))    {
  702.                         p1 = CTRL_FIVE;
  703.                         p2 = LEFTSHIFT;
  704.                     }
  705.                     break;
  706.                 case DN:
  707.                     if (!isDerivedFrom(wnd, LISTBOX) &&
  708.                             !isDerivedFrom(wnd, COMBOBOX))
  709.                         p1 = '\t';
  710.                     break;
  711.                 case FWD:
  712.                     if (!isDerivedFrom(wnd, EDITBOX))
  713.                         p1 = '\t';
  714.                     break;
  715.                 case '\r':
  716.                     if (isDerivedFrom(wnd, EDITBOX))
  717.                         if (isMultiLine(wnd))
  718.                             break;
  719.                     if (isDerivedFrom(wnd, BUTTON))
  720.                         break;
  721.                     SendMessage(GetParent(wnd), COMMAND, ID_OK, 0);
  722.                     return TRUE;
  723.                 default:
  724.                     break;
  725.             }
  726.             break;
  727.         case SETFOCUS:
  728.             if (p1)    {
  729.                 DefaultWndProc(wnd, msg, p1, p2);
  730.                 GetParent(wnd)->dFocus = ct;
  731.                 SendMessage(GetParent(wnd), COMMAND,
  732.                     inFocusCommand(db), ENTERFOCUS);
  733.                 return TRUE;
  734.             }
  735.             else 
  736.                 SendMessage(GetParent(wnd), COMMAND,
  737.                     inFocusCommand(db), LEAVEFOCUS);
  738.             break;
  739.         case CLOSE_WINDOW:
  740.             if (ct != NULL)
  741.                 if (GetParent(wnd)->ReturnCode == ID_OK &&
  742.                         (ct->class == EDITBOX || ct->class == COMBOBOX))
  743.                     if (wnd->TextChanged)
  744.                         if ((ct->itext = realloc(ct->itext,    strlen(wnd->text)+1)) != NULL)    {
  745.                             strcpy(ct->itext, wnd->text);
  746.                             if (!isMultiLine(wnd))    {
  747.                                 char *cp = ct->itext+strlen(ct->itext)-1;
  748.                                 if (*cp == '\n')
  749.                                     *cp = '\0';
  750.                             }
  751.                         }
  752.             break;
  753.         default:
  754.             break;
  755.     }
  756.     return DefaultWndProc(wnd, msg, p1, p2);
  757. }
  758.  
  759. /* ----- Create unambiguous path from file spec, filling in the
  760.      drive and directory if incomplete. Optionally change to
  761.      the new drive and subdirectory ------ */
  762. void CreatePath(char *path, char *fspec, int InclName, int Change)
  763. {
  764.     int cm = 0;
  765.     unsigned currdrive;
  766.     char currdir[64];
  767.     char *cp;
  768.  
  769.     if (!Change)    {
  770.         /* ----- save the current drive and subdirectory ----- */
  771.         currdrive = getdisk();
  772.         getcwd(currdir, sizeof currdir);
  773.         memmove(currdir, currdir+2, strlen(currdir+1));
  774.         cp = currdir+strlen(currdir)-1;
  775.         if (*cp == '\\')
  776.             *cp = '\0';
  777.     }
  778.  
  779.     *drive = *dir = *name = *ext = '\0';
  780.     fnsplit(fspec, drive, dir, name, ext);
  781.     if (!InclName)
  782.         *name = *ext = '\0';
  783.     *drive = toupper(*drive);
  784.  
  785.     if (*ext)
  786.         cm |= EXTENSION;
  787.     if (InclName && *name)
  788.         cm |= FILENAME;
  789.     if (*dir)
  790.         cm |= DIRECTORY;
  791.     if (*drive)
  792.         cm |= DRIVE;
  793.  
  794.     if (cm & DRIVE)
  795.         setdisk(*drive - 'A');
  796.     else     {
  797.         *drive = getdisk();
  798.         *drive += 'A';
  799.     }
  800.  
  801.     if (cm & DIRECTORY)    {
  802.         cp = dir+strlen(dir)-1;
  803.         if (*cp == '\\')
  804.             *cp = '\0';
  805.         chdir(dir);
  806.     }
  807.     getcwd(dir, sizeof dir);
  808.     memmove(dir, dir+2, strlen(dir+1));
  809.  
  810.     if (InclName)    {
  811.         if (!(cm & FILENAME))
  812.             strcpy(name, "*");
  813.         if (!(cm & EXTENSION))
  814.             strcpy(ext, ".*");
  815.     }
  816.     else
  817.         *name = *ext = '\0';
  818.     if (dir[strlen(dir)-1] != '\\')
  819.         strcat(dir, "\\");
  820.     memset(path, 0, sizeof path);
  821.     fnmerge(path, drive, dir, name, ext);
  822.  
  823.     if (!Change)    {
  824.         setdisk(currdrive);
  825.         chdir(currdir);
  826.     }
  827. }
  828.  
  829. static void ChangeFocus(WINDOW wnd, int direc)
  830. {
  831.     DBOX *db = wnd->extension;
  832.      CTLWINDOW *ct = db->ctl;
  833.      CTLWINDOW *ctt;
  834.  
  835.     /* --- find the control that has the focus --- */
  836.     while (ct->class)    {
  837.         if (ct == wnd->dFocus)
  838.             break;
  839.         ct++;
  840.     }
  841.     if (ct->class)    {
  842.         ctt = ct;
  843.         do    {
  844.             /* ----- point to next or previous control ----- */
  845.             if (direc)    {
  846.                 ct++;
  847.                 if (ct->class == 0)
  848.                     ct = db->ctl;
  849.             }
  850.             else    {
  851.                 if (ct == db->ctl)
  852.                     while (ct->class)
  853.                         ct++;
  854.                 --ct;
  855.             }
  856.  
  857.             if (ct->class != BOX && ct->class != TEXT)    {
  858.                 SendMessage(ct->wnd, SETFOCUS, TRUE, 0);
  859.                 SendMessage(ctt->wnd, PAINT, 0, 0);
  860.                 SendMessage(ct->wnd, PAINT, 0, 0);
  861.                 break;
  862.             }
  863.         } while (ct != ctt);
  864.     }
  865. }
  866.